/* threadtest.cc 
	Simple test case for the threads assignment.

	Create two threads, and have them context switch
	back and forth between themselves by calling Thread::Yield, 
	to illustratethe inner workings of the thread system.

	Copyright (c) 1992-1993 The Regents of the University of California.
	All rights reserved.  See copyright.h for copyright notice and limitation 
	of liability and disclaimer of warranty provisions. */

#include "copyright.h"
#include "system.h"
#ifdef CHANGED
#include "synch.h"
#include "theater.h"
#include <stdio.h>
#endif

#ifdef CHANGED
/* --------------------------------------------------
   Test Suite
   --------------------------------------------------


   --------------------------------------------------
   Test 1 - see TestSuite() for details
   -------------------------------------------------- */
Semaphore t1_s1("t1_s1",0);       /* To make sure t1_t1 acquires the
                                     lock before t1_t2 */
Semaphore t1_s2("t1_s2",0);       /* To make sure t1_t2 Is waiting on the 
                                     lock before t1_t3 releases it */
Semaphore t1_s3("t1_s3",0);       /* To make sure t1_t1 does not release the
                                     lock before t1_t3 tries to acquire it */
Semaphore t1_done("t1_done",0);   /* So that TestSuite knows when Test 1 is
                                     done */
Lock t1_l1("t1_l1");		  /* the lock tested in Test 1 */

/* --------------------------------------------------
   t1_t1() -- test1 thread 1
       This is the rightful lock owner
   -------------------------------------------------- */
void t1_t1() {
    t1_l1.Acquire();
    t1_s1.V();  /* Allow t1_t2 to try to Acquire Lock */
 
    printf ("%s: Acquired Lock %s, waiting for t3\n",currentThread->getName(),
	    t1_l1.getName());
    t1_s3.P();
    printf ("%s: working in CS\n",currentThread->getName());
    for (int i = 0; i < 1000000; i++) ;
    printf ("%s: Releasing Lock %s\n",currentThread->getName(),
	    t1_l1.getName());
    t1_l1.Release();
    t1_done.V();
}

/* --------------------------------------------------
   t1_t2() -- test1 thread 2
       This thread will wait on the held lock.
   -------------------------------------------------- */
void t1_t2() {

    t1_s1.P();	/* Wait until t1 has the lock */
    t1_s2.V();  /* Let t3 try to acquire the lock */

    printf("%s: trying to acquire lock %s\n",currentThread->getName(),
	    t1_l1.getName());
    t1_l1.Acquire();

    printf ("%s: Acquired Lock %s, working in CS\n",currentThread->getName(),
	    t1_l1.getName());
    for (int i = 0; i < 10; i++)
	;
    printf ("%s: Releasing Lock %s\n",currentThread->getName(),
	    t1_l1.getName());
    t1_l1.Release();
    t1_done.V();
}

/* --------------------------------------------------
   t1_t3() -- test1 thread 3
       This thread will try to release the lock illegally
   -------------------------------------------------- */
void t1_t3() {

    t1_s2.P();	/* Wait until t2 is ready to try to acquire the lock */

    t1_s3.V();	/* Let t1 do it's stuff */
    for ( int i = 0; i < 3; i++ ) {
	printf("%s: Trying to release Lock %s\n",currentThread->getName(),
	       t1_l1.getName());
	t1_l1.Release();
    }
}

/* --------------------------------------------------
   Test 2 - see TestSuite() for details
   -------------------------------------------------- */
Lock t2_l1("t2_l1");		/* For mutual exclusion */
Condition t2_c1("t2_c1");	/* The condition variable to test */
Semaphore t2_s1("t2_s1",0);	/* To ensure the Signal comes before the wait */
Semaphore t2_done("t2_done",0);     /* So that TestSuite knows when Test 2 is
									   done */

/* --------------------------------------------------
   t2_t1() -- test 2 thread 1
       This thread will signal a variable with nothing waiting
   -------------------------------------------------- */
void t2_t1() {
    t2_l1.Acquire();
    printf("%s: Lock %s acquired, signalling %s\n",currentThread->getName(),
	   t2_l1.getName(), t2_c1.getName());
    t2_c1.Signal(&t2_l1);
    printf("%s: Releasing Lock %s\n",currentThread->getName(),
	   t2_l1.getName());
    t2_l1.Release();
    t2_s1.V();	/* release t2_t2 */
    t2_done.V();
}

/* --------------------------------------------------
   t2_t2() -- test 2 thread 2
       This thread will wait on a pre-signalled variable
   -------------------------------------------------- */
void t2_t2() {
    t2_s1.P();	/* Wait for t2_t1 to be done with the lock */
    t2_l1.Acquire();
    printf("%s: Lock %s acquired, waiting on %s\n",currentThread->getName(),
	   t2_l1.getName(), t2_c1.getName());
    t2_c1.Wait(&t2_l1);
    printf("%s: Releasing Lock %s\n",currentThread->getName(),
	   t2_l1.getName());
    t2_l1.Release();
}
/* --------------------------------------------------
   Test 3 - see TestSuite() for details
   -------------------------------------------------- */
Lock t3_l1("t3_l1");		/* For mutual exclusion */
Condition t3_c1("t3_c1");	/* The condition variable to test */
Semaphore t3_s1("t3_s1",0);	/* To ensure the Signal comes before the wait */
Semaphore t3_done("t3_done",0); /* So that TestSuite knows when Test 3 is
                                   done */

/* --------------------------------------------------
   t3_waiter()
       These threads will wait on the t3_c1 condition variable.  Only
       one t3_waiter will be released
   -------------------------------------------------- */
void t3_waiter() {
    t3_l1.Acquire();
    t3_s1.V();		/* Let the signaller know we're ready to wait */
    printf("%s: Lock %s acquired, waiting on %s\n",currentThread->getName(),
	   t3_l1.getName(), t3_c1.getName());
    t3_c1.Wait(&t3_l1);
    printf("%s: freed from %s\n",currentThread->getName(), t3_c1.getName());
    t3_l1.Release();
    t3_done.V();
}


/* --------------------------------------------------
   t3_signaller()
       This threads will signal the t3_c1 condition variable.  Only
       one t3_signaller will be released
   -------------------------------------------------- */
void t3_signaller() {

    /* Don't signal until someone's waiting */
    
    for ( int i = 0; i < 5 ; i++ ) 
	t3_s1.P();
    t3_l1.Acquire();
    printf("%s: Lock %s acquired, signalling %s\n",currentThread->getName(),
	   t3_l1.getName(), t3_c1.getName());
    t3_c1.Signal(&t3_l1);
    printf("%s: Releasing %s\n",currentThread->getName(), t3_l1.getName());
    t3_l1.Release();
    t3_done.V();
}
 
/* --------------------------------------------------
   Test 4 - see TestSuite() for details
   -------------------------------------------------- */
Lock t4_l1("t4_l1");		/* For mutual exclusion */
Condition t4_c1("t4_c1");	/* The condition variable to test */
Semaphore t4_s1("t4_s1",0);	/* To ensure the Signal comes before the wait */
Semaphore t4_done("t4_done",0); /* So that TestSuite knows when Test 4 is
                                   done */

/* --------------------------------------------------
   t4_waiter()
       These threads will wait on the t4_c1 condition variable.  All
       t4_waiters will be released
   -------------------------------------------------- */
void t4_waiter() {
    t4_l1.Acquire();
    t4_s1.V();		/* Let the signaller know we're ready to wait */
    printf("%s: Lock %s acquired, waiting on %s\n",currentThread->getName(),
	   t4_l1.getName(), t4_c1.getName());
    t4_c1.Wait(&t4_l1);
    printf("%s: freed from %s\n",currentThread->getName(), t4_c1.getName());
    t4_l1.Release();
    t4_done.V();
}


/* --------------------------------------------------
   t2_signaller()
       This thread will broadcast to the t4_c1 condition variable.
       All t4_waiters will be released
   -------------------------------------------------- */
void t4_signaller() {

    /* Don't broadcast until someone's waiting */
    
    for ( int i = 0; i < 5 ; i++ ) 
	t4_s1.P();
    t4_l1.Acquire();
    printf("%s: Lock %s acquired, broadcasting %s\n",currentThread->getName(),
	   t4_l1.getName(), t4_c1.getName());
    t4_c1.Broadcast(&t4_l1);
    printf("%s: Releasing %s\n",currentThread->getName(), t4_l1.getName());
    t4_l1.Release();
    t4_done.V();
}
/* --------------------------------------------------
   Test 5 - see TestSuite() for details
   -------------------------------------------------- */
Lock t5_l1("t5_l1");		/* For mutual exclusion */
Lock t5_l2("t5_l2");		/* Second lock for the bad behavior */
Condition t5_c1("t5_c1");	/* The condition variable to test */
Semaphore t5_s1("t5_s1",0);	/* To make sure t5_t2 acquires the lock after
                                   t5_t1 */

/* --------------------------------------------------
   t5_t1() -- test 5 thread 1
       This thread will wait on a condition under t5_l1
   -------------------------------------------------- */
void t5_t1() {
    t5_l1.Acquire();
    t5_s1.V();	/* release t5_t2 */
    printf("%s: Lock %s acquired, waiting on %s\n",currentThread->getName(),
	   t5_l1.getName(), t5_c1.getName());
    t5_c1.Wait(&t5_l1);
    printf("%s: Releasing Lock %s\n",currentThread->getName(),
	   t5_l1.getName());
    t5_l1.Release();
}

/* --------------------------------------------------
   t5_t1() -- test 5 thread 1
       This thread will wait on a t5_c1 condition under t5_l2, which is
       a Fatal error
   -------------------------------------------------- */
void t5_t2() {
    t5_s1.P();	/* Wait for t5_t1 to get into the monitor */
    t5_l1.Acquire();
    t5_l2.Acquire();
    printf("%s: Lock %s acquired, signalling %s\n",currentThread->getName(),
	   t5_l2.getName(), t5_c1.getName());
    t5_c1.Signal(&t5_l2);
    printf("%s: Releasing Lock %s\n",currentThread->getName(),
	   t5_l2.getName());
    t5_l2.Release();
    printf("%s: Releasing Lock %s\n",currentThread->getName(),
	   t5_l1.getName());
    t5_l1.Release();
}

/* --------------------------------------------------
   TestSuite()
       This is the main thread of the test suite.  It runs the
       following tests:
  
         1.  Show that a thread trying to release a lock it does not
         hold does not work
  
         2.  Show that Signals are not stored -- a Signal with no
         thread waiting is ignored
  
         3.  Show that Signal only wakes 1 thread
  
  	 4.  Show that Broadcast wakes all waiting threads
  
         5.  Show that Signalling a thread waiting under one lock
         while holding another is a Fatal error
  
       Fatal errors terminate the thread in question.
   -------------------------------------------------- */
void TestSuite() {
    Thread *t;
    char *name;
    int i;
    
    /* Test 1 */

    printf("Starting Test 1\n");

    t = new Thread("t1_t1");
    t->Fork((VoidFunctionPtr)t1_t1,0);

    t = new Thread("t1_t2");
    t->Fork((VoidFunctionPtr)t1_t2,0);

    t = new Thread("t1_t3");
    t->Fork((VoidFunctionPtr)t1_t3,0);

    /* Wait for Test 1 to complete */
    for (  i = 0; i < 2; i++ )
	t1_done.P();

    /* Test 2 */
	
	printf("\n");
    printf("Starting Test 2.  Note that it is an error if thread t2_t2\n");
    printf("completes\n");

    t = new Thread("t2_t1");
    t->Fork((VoidFunctionPtr)t2_t1,0);

    t = new Thread("t2_t2");
    t->Fork((VoidFunctionPtr)t2_t2,0);

    /* Wait for Test 2 to complete */
    t2_done.P();

    /* Test 3 */

	
	printf("\n");
    printf("Starting Test 3\n");

    for (  i = 0 ; i < 5 ; i++ ) {
	name = new char [20];
	sprintf(name,"t3_waiter%d",i);
	t = new Thread(name);
	t->Fork((VoidFunctionPtr)t3_waiter,0);
    }
    t = new Thread("t3_signaller");
    t->Fork((VoidFunctionPtr)t3_signaller,0);

    /* Wait for Test 3 to complete */
    for (  i = 0; i < 2; i++ )
	t3_done.P();

    /* Test 4 */

	printf("\n");
    printf("Starting Test 4\n");

    for (  i = 0 ; i < 5 ; i++ ) {
	name = new char [20];
	sprintf(name,"t4_waiter%d",i);
	t = new Thread(name);
	t->Fork((VoidFunctionPtr)t4_waiter,0);
    }
    t = new Thread("t4_signaller");
    t->Fork((VoidFunctionPtr)t4_signaller,0);

    /* Wait for Test 4 to complete */
    for (  i = 0; i < 6; i++ )
	t4_done.P();

    /* Test 5 */

	printf("\n");
    printf("Starting Test 5.  Note that it is an error if thread t5_t1\n");
    printf("completes\n");

    t = new Thread("t5_t1");
    t->Fork((VoidFunctionPtr)t5_t1,0);

    t = new Thread("t5_t2");
    t->Fork((VoidFunctionPtr)t5_t2,0);

}
#endif

/*----------------------------------------------------------------------
   SimpleThread
   	Loop 5 times, yielding the CPU to another ready thread 
  	each iteration.
  
  	"which" is simply a number identifying the thread, for debugging
  	purposes.
  ---------------------------------------------------------------------- */

void
SimpleThread(int which)
{
    int num;
    
    for (num = 0; num < 5; num++) {
	printf("*** thread %d looped %d times\n", which, num);
        currentThread->Yield();
    }
}

/*----------------------------------------------------------------------
   ThreadTest
   	Set up a ping-pong between two threads, by forking a thread 
  	to call SimpleThread, and then calling SimpleThread ourselves.
  ---------------------------------------------------------------------- */

#ifdef CHANGED
/*Our own tests*/

void subMenu(){
	
	printf("Please choose of the following options.\n");
	printf("1. Something.\n");

	int choice;
	scanf("%d", &choice);
	
	switch(choice){
	case 1:
		printf("Uh...");
		break;	
	
	}

}


/*Required Tests*/

/*Test 1: Shortest Line*/

const int MAX_TC_TEST = 5;
	
/* Customer Finding Ticket Line */
Lock* ticketClerkLineLockTest; /* Lock for choosing a line */
Condition* ticketClerkLineConditionVariableTest[MAX_TC_TEST];
int ticketClerkLineCountTest[MAX_TC_TEST];
int ticketClerkStateTest[MAX_TC_TEST]; /* 0 = NOT_BUSY, 1 = BUSY, 2 = ON_BREAK, -1 = NOT_AVAILABLE */


void shortestLine(int myIndex){

	
	/*BEGIN: Test code*/
	
	/*BEGIN: Customer - TicketClerk Interaction*/
	
	int myTicketClerk = -1; /* index = -1 */
	ticketClerkLineLockTest->Acquire(); /* Lock for choosing a line */
	/* look for a clerk in the NOT_BUSY state */
	for(int i = 0; i < MAX_TC_TEST; i++){
		/* need to have a check to see if the clerk "exists" and is NOT_BUSY */
		if(ticketClerkStateTest[i] == 0){
			/* don't have to wait, just go to clerk */
			myTicketClerk = i;
			ticketClerkStateTest[i] = 1;
			printf("HCust%i: myTicketClerk is %i\n", myIndex, myTicketClerk);
			break;
		}
	}
	
	/* if I don't have a clerk (myTicketClerk = -1), choose shortest line */
	if(myTicketClerk == -1){
		printf("HCust%i: Finding the shortest line\n", myIndex);
		int shortestTicketClerkLine = 0; /* index = 0 */
		int shortestTicketClerkLineLength = ticketClerkLineCountTest[0];
		
		for(int i = 1; i < MAX_TC_TEST; i++){
			if(shortestTicketClerkLineLength > ticketClerkLineCountTest[i] && (ticketClerkStateTest[i] == 0 || ticketClerkStateTest[i] == 1)){ /* if there's a shorter line than current line */
				shortestTicketClerkLine = i;
				shortestTicketClerkLineLength = ticketClerkLineCountTest[i];
			}
		}
		
		/* Steps
		1. I must have the shortest line at this point 
		2. Get in that line 
		3. Sleep and give up the lock, will reacquire the lock when signaled */
		
		printf("HCust%i: Getting in a line\n", myIndex);
		myTicketClerk = shortestTicketClerkLine;
		printf("HCust%i: myTicketClerk is %i\n", myIndex, myTicketClerk);
		ticketClerkLineCountTest[myTicketClerk]++;
		
		ticketClerkLineConditionVariableTest[myTicketClerk]->Wait(ticketClerkLineLockTest);
		
	}
	
	ticketClerkLineLockTest->Release();
	
	/*END: Test code*/

}


void shortestLineInitialize(){

	/*BEGIN: Customer Initialization*/
		
	int numCustomers = 10;
			
	for ( int i=0; i < numCustomers ; i++ ) {
		
		Thread *t = new Thread("Head Customer");
		t->Fork( shortestLine, i);
	
	}	
	
	/*END: Customer Initialization*/

	/*BEGIN: Pseudo-Ticket Clerk*/
	
	ticketClerkLineLockTest = new Lock("TicketClerk Line Lock");
	
	for(int i = 0; i < MAX_TC_TEST; i++){
	
		ticketClerkLineConditionVariableTest[i] = new Condition("TicketClerk Line CV");
		ticketClerkLineCountTest[i] = 0;				
		ticketClerkStateTest[i] = 0;
	}

	/*END: Pseudo-Ticket Clerk*/
}



/*Test 2: Managers read from only 1 register at a time*/

/*Test 2 "Global Vars*/
const int MAX_TC_TEST_test2 = 5;
Lock * ticketClerkLock_test2[MAX_TC_TEST_test2];
int ticketClerkRegister_test2[MAX_TC_TEST_test2];
int managerMoney_test2;



void manager_test2(int myIndex){

	for(int k = 0; k < 1; k++){

		int loopend = rand()%30;
		
		for(int i = 0; i < loopend; i++){
			currentThread->Yield();
		}
		
		for(int j = 0; j < MAX_TC_TEST; j++){
		
			ticketClerkLock_test2[j]->Acquire();
			printf("Register Lock %i Acquired\n", j);
			currentThread->Yield();
			managerMoney_test2 += ticketClerkRegister_test2[j];
				
			printf("Manager collected %i from TicketClerk%i.\n", ticketClerkRegister_test2[j], j);
			printf("Total money made by office = %i\n", managerMoney_test2);
			currentThread->Yield();			
			ticketClerkRegister_test2[j] = 0;
			ticketClerkLock_test2[j]->Release();
			printf("Register Lock %i Released\n", j);
			currentThread->Yield();
		}

		printf("Total money made by office = %i\n", managerMoney_test2);
	}

}

void SalesClerk_test2(int myIndex){

	for(int k = 0; k < 1; k++){

		int loopend = rand()%20;
		int numtick = 1;

		ticketClerkLock_test2[myIndex]->Acquire();
		

		ticketClerkRegister_test2[myIndex] += numtick*10;
		
		printf("TicketClerk %i has an order for %i and the cost is %i.\n", myIndex, numtick, numtick*10);
		
		ticketClerkLock_test2[myIndex]->Release();

		/*
		for(int i = 0; i < loopend; i++){
			currentThread->Yield();
		}
		*/
	}
}

void collectMoneyInitialize(){

	/*BEGIN: Clerk Initialization*/
		
			
	for ( int i=0; i < MAX_TC_TEST ; i++ ) {
		
		ticketClerkLock_test2[i] = new Lock("TicketClerk Lock");
		ticketClerkRegister_test2[i] = 0;
		
		Thread *t = new Thread("Clerk");
		t->Fork( SalesClerk_test2, i);
		
	}	
	
	printf("Number of Ticket Clerks = %i\n",MAX_TC_TEST_test2);
	
	/*END: Clerk Initialization*/

	/*BEGIN: Manager*/
	
	managerMoney_test2 = 0;

}
	
void collectMoney(){

	collectMoneyInitialize();
	
		Thread *t = new Thread("Manager");
	t->Fork( manager_test2, 1);
}




/*Test 3: Obedient customers*/

/*Test 3 Global Vars*/
const int MAX_TC_T3 = 1;
	const int MAX_CC_T3 = 1;
	const int MAX_TT_T3 = 1;
	const int MAX_GROUPS_T3 = 1;
	int customerNumber_TC3[MAX_GROUPS_T3*5];
	int customerGroupNumber_TC3[MAX_GROUPS_T3*5];
	int customerIsHeadCustomer_TC3[MAX_GROUPS_T3*5];
	int groupSize_TC3[MAX_GROUPS_T3];
	int groupMoney_TC3[MAX_GROUPS_T3];
	int groupTickets_TC3[MAX_GROUPS_T3];
	int headCustomerNumber_TC3[MAX_GROUPS_T3]; /*the head customer's customer number*/

	/* Customer Finding Ticket Line */
	Lock* ticketClerkLineLock_TC3; /* Lock for choosing a 	line */
	Condition* ticketClerkLineConditionVariable_TC3[MAX_TC_T3];
	int ticketClerkLineCount_TC3[MAX_TC_T3];
	int ticketClerkState_TC3[MAX_TC_T3]; /* 0 = NOT_BUSY, 1 = BUSY, 2 = ON_BREAK, -1 = NOT_AVAILABLE */

/* Customer - TicketClerk Interaction */
Lock* ticketClerkLock_TC3[MAX_TC_T3]; /* Lock for Customer - TicketClerk Interaction */
Condition* ticketClerkConditionVariable_TC3[MAX_TC_T3];
int ticketClerkRegister_TC3[MAX_TC_T3]; /* registers for the ticket clerks */
int ticketClerkNumToSell_TC3[MAX_TC_T3]; /* Number of tickets to sell in one transaction*/

/* Customer Finding Concession Line */
Lock* concessionClerkLineLock_TC3; /* Lock for choosing a line */
Condition* concessionClerkLineConditionVariable_TC3[MAX_CC_T3];
int concessionClerkLineCount_TC3[MAX_CC_T3];
int concessionClerkState_TC3[MAX_CC_T3]; /* 0 = NOT_BUSY, 1 = BUSY, 2 = ON_BREAK, -1 = NOT_AVAILABLE */

/* Customer - ConcessionClerk Interaction */
Lock* concessionClerkLock_TC3[MAX_CC_T3]; /* Lock for Customer - ConcessionClerk Interaction */
Condition* concessionClerkConditionVariable_TC3[MAX_CC_T3];
int concessionClerkRegister_TC3[MAX_CC_T3]; /*registers for the Concession clerks*/
int concessionClerkPopcornToSell_TC3[MAX_CC_T3]; /*number of popcorn selling*/
int concessionClerkSodaToSell_TC3[MAX_CC_T3]; /*number of sodas selling*/ 

/*Customer Finding TicketTaker Line*/
Lock* ticketTakerLineLock_TC3; /* Lock for choosing a line */
Condition* ticketTakerLineConditionVariable_TC3[MAX_TT_T3];
int ticketTakerLineCount_TC3[MAX_TT_T3];
int ticketTakerState_TC3[MAX_TT_T3]; /* 0 = NOT_BUSY, 1 = BUSY, 2 = ON_BREAK, -1 = NOT_AVAILABLE */

/*Customer - TicketTaker Interaction*/
Lock* ticketTakerLock_TC3[MAX_TT_T3]; /* Lock for Customer - TicketTaker Interaction */
Condition* ticketTakerConditionVariable_TC3[MAX_TT_T3];
int ticketTakerCounter_TC3[MAX_TT_T3];
int numberAdmitted_TC3;


void obedientCustomerCust(int myIndex){

	/*BEGIN: Customer - TicketClerk Interaction*/
	
	int myTicketClerk = 0; /* 0 for testing */
	ticketClerkLineLock_TC3->Acquire(); /* Lock for choosing a line */
	
	/* don't have to wait, just go to clerk */
			myTicketClerk = 0;
			ticketClerkState_TC3[0] = 1;
	
	ticketClerkLineLock_TC3->Release();
	ticketClerkLock_TC3[myTicketClerk]->Acquire();
	
	/*STEP 1: Customer-TicketClerk, Sets the global variable indicating the number of tickets he wants to buy.*/
	ticketClerkNumToSell_TC3[myTicketClerk] = 1;
	
	ticketClerkConditionVariable_TC3[myTicketClerk]->Signal(ticketClerkLock_TC3[myTicketClerk]);
	ticketClerkConditionVariable_TC3[myTicketClerk]->Wait(ticketClerkLock_TC3[myTicketClerk]);

	/*STEP 2: Customer-TicketClerk, Customer hands out the cash.*/
	groupMoney_TC3[myIndex] -= 1*12;
	
	ticketClerkConditionVariable_TC3[myTicketClerk]->Signal(ticketClerkLock_TC3[myTicketClerk]);
	ticketClerkConditionVariable_TC3[myTicketClerk]->Wait(ticketClerkLock_TC3[myTicketClerk]);
	
	/*STEP 3: Customer-TicketClerk, After the ticket clerks sells the tickets, he takes the tickts (sets groupTickets)*/
	groupTickets_TC3[myIndex] = 1;

	ticketClerkConditionVariable_TC3[myTicketClerk]->Signal(ticketClerkLock_TC3[myTicketClerk]);
	
	printf("CUST is leaving TC\n");
	ticketClerkLock_TC3[myTicketClerk]->Release();
	
	
	/*END: Customer - TicketClerk Interaction*/
	/*BEGIN: Customer - ConcessionClerk Interaction*/
	
	
	int myConcessionClerk = 0; /* test = 0 */
		
	concessionClerkLineLock_TC3->Acquire(); /* Lock for choosing a line */
		
		/* don't have to wait, just go to clerk */
		myConcessionClerk = 0;
		concessionClerkState_TC3[0] = 1;
				
		concessionClerkLineLock_TC3->Release();
		concessionClerkLock_TC3[myConcessionClerk]->Acquire();
		
		/*STEP 1: Customer-ConcessionClerk, Tells Concession clerk here's there and read to order.*/
		printf("Customer 0 in Group 0 is walking up to ConcessionClerk0 to buy 1 popcorn and 1 soda.\n");
		
		concessionClerkPopcornToSell_TC3[myConcessionClerk] = 1;  /* simulate asking for 1 */
		concessionClerkSodaToSell_TC3[myConcessionClerk] = 1;
		
		concessionClerkConditionVariable_TC3[myConcessionClerk]->Signal(concessionClerkLock_TC3[myConcessionClerk]);
		concessionClerkConditionVariable_TC3[myConcessionClerk]->Wait(concessionClerkLock_TC3[myConcessionClerk]);
		
		/*STEP 2: Customer-ConcessionClerk, Customer hands out the cash*/
		groupMoney_TC3[myIndex] -= 1*5 + 1*4;
		
		concessionClerkConditionVariable_TC3[myConcessionClerk]->Signal(concessionClerkLock_TC3[myConcessionClerk]);
		concessionClerkConditionVariable_TC3[myConcessionClerk]->Wait(concessionClerkLock_TC3[myConcessionClerk]);
		
		/*STEP 3: Customer-ConcessionClerk, After the concession clerks sells the food, he takes the food*/
		
		/*TODO: Acknowledge that the purchase of food went through somehow.*/

		concessionClerkConditionVariable_TC3[myConcessionClerk]->Signal(concessionClerkLock_TC3[myConcessionClerk]);
		
		printf("CUST is now leaving CC\n");
		concessionClerkLock_TC3[myConcessionClerk]->Release();		
		
		
		/*END: Customer - ConcessionClerk Interaction*/
		/*BEGIN: Customer - TicketTaker Interaction*/
		
		int myTicketTaker = 0; /* test = 0 */
		ticketTakerLineLock_TC3->Acquire();

		
					myTicketTaker = 0;
					ticketTakerState_TC3[0] = 1;
					ticketTakerLineLock_TC3->Release();
			
		
	
			ticketTakerLock_TC3[myTicketTaker]->Acquire();
			/* Customer is now at counter */
		
			printf("Customer 0 in Group 0 is walking up to TicketTaker0 to give 1 ticket.\n");
			ticketTakerCounter_TC3[myTicketTaker] = 1;
		
			ticketTakerConditionVariable_TC3[myTicketTaker]->Signal(ticketTakerLock_TC3[myTicketTaker]);
			ticketTakerConditionVariable_TC3[myTicketTaker]->Wait(ticketTakerLock_TC3[myTicketTaker]);
		
			if(ticketTakerCounter_TC3[myTicketTaker] == 1){
				ticketTakerCounter_TC3[myTicketTaker] = -1;
				ticketTakerConditionVariable_TC3[myTicketTaker]->Signal(ticketTakerLock_TC3[myTicketTaker]);
				ticketTakerLock_TC3[myTicketTaker]->Release();
				printf("CUST will now leave and go in the theater\n");
				
			} else {
				ticketTakerCounter_TC3[myTicketTaker] = -1;
				ticketTakerConditionVariable_TC3[myTicketTaker]->Signal(ticketTakerLock_TC3[myTicketTaker]);
				printf("HCust%i: Why is TT%i such a negative nancy?\n", myIndex, myTicketTaker);
				ticketTakerLock_TC3[myTicketTaker]->Release();
			}
	
}

void obedientCustomerTC(int myIndex){
	int flag = 1;
	while(flag){ /* while true */
		ticketClerkLineLock_TC3->Acquire(); /* Lock for choosing a line */
		
		/* no one is in my line */
		ticketClerkState_TC3[myIndex] = 0; /* state = NOT_BUSY */

		/* done with clerk's first monitor.
		   clerk is ready to wait
		   by acquiring the next lock before releasing the current lock,
		   we guarantee that we get the lock first */		
		ticketClerkLock_TC3[myIndex]->Acquire();
		ticketClerkLineLock_TC3->Release();
		
		/*STEP 1: TicketClerk-Customer, Waiting for the customer to come up to ticket window so it can begin.*/	
		ticketClerkConditionVariable_TC3[myIndex]->Wait(ticketClerkLock_TC3[myIndex]);
		
		/*STEP 2: TicketClerk-Customer, Tells Customer the total, and waits for the response (number of tickets)*/
		/*TODO: Check if customer can make a purchase?*/
		ticketClerkConditionVariable_TC3[myIndex]->Signal(ticketClerkLock_TC3[myIndex]);
		ticketClerkConditionVariable_TC3[myIndex]->Wait(ticketClerkLock_TC3[myIndex]);
		
		/*STEP 3: TicketClerk-Customer, Takes cash from customer, puts in register.*/
		ticketClerkRegister_TC3[myIndex] = ticketClerkNumToSell_TC3[myIndex]*12;	
		ticketClerkNumToSell_TC3[myIndex] = 0; /*Resets to 0 inbetween transactions.*/
		printf("TC has dismissed CUST\n");  //test
		ticketClerkConditionVariable_TC3[myIndex]->Signal(ticketClerkLock_TC3[myIndex]);
		ticketClerkConditionVariable_TC3[myIndex]->Wait(ticketClerkLock_TC3[myIndex]);
		ticketClerkLock_TC3[myIndex]->Release();
		printf("TC will now look for next customer\n");
	}
}

void obedientCustomerCC(int myIndex){
	int flag = 1;
	
	while(flag){ /* while true */
		concessionClerkLineLock_TC3->Acquire(); /* Lock for choosing a line */
	
			concessionClerkState_TC3[myIndex] = 0; /* state = NOT_BUSY */
			
		/* done with concession clerk's first monitor.
		   concession clerk is ready to wait
		   by acquiring the next lock before releasing the current lock,
		   we guarantee that we get the lock first */
		
		concessionClerkLock_TC3[myIndex]->Acquire();  
		concessionClerkLineLock_TC3->Release();
		
		/*STEP 1: ConcessionClerk-Customer, Waiting for the customer to come up to the counter.*/
		concessionClerkConditionVariable_TC3[myIndex]->Wait(concessionClerkLock_TC3[myIndex]);
		
		/*STEP 2: ConcessionClerk-Customer, Tells customer the total*/
		concessionClerkConditionVariable_TC3[myIndex]->Signal(concessionClerkLock_TC3[myIndex]);
		concessionClerkConditionVariable_TC3[myIndex]->Wait(concessionClerkLock_TC3[myIndex]);
		
		/*STEP 3: ConcessionClerk-Customer, Takes cash from customer.*/
		concessionClerkRegister_TC3[myIndex] = (concessionClerkPopcornToSell_TC3[myIndex]*5 + concessionClerkSodaToSell_TC3[myIndex]*4);
		
		concessionClerkPopcornToSell_TC3[myIndex] = 0;
		concessionClerkSodaToSell_TC3[myIndex] = 0;
		
		concessionClerkConditionVariable_TC3[myIndex]->Signal(concessionClerkLock_TC3[myIndex]);
		printf("CC has dismissed CUST\n");  //test
		concessionClerkConditionVariable_TC3[myIndex]->Wait(concessionClerkLock_TC3[myIndex]);
		concessionClerkLock_TC3[myIndex]->Release();
		printf("CC will now look for next customer\n");  //test
		
	}
}

void obedientCustomerTT(int myIndex){
	while(1){
		ticketTakerLineLock_TC3->Acquire();  /* Look in line */
			ticketTakerState_TC3[myIndex] = 0;
		
		ticketTakerLock_TC3[myIndex]->Acquire();
		ticketTakerLineLock_TC3->Release();
		ticketTakerConditionVariable_TC3[myIndex]->Wait(ticketTakerLock_TC3[myIndex]);
		
		if(ticketTakerCounter_TC3[myIndex] > 0){
			if(1){
				/* let them in */
				printf("TT has allowed CUST to enter theater\n");  //test
				numberAdmitted_TC3 += ticketTakerCounter_TC3[myIndex];			
				ticketTakerCounter_TC3[myIndex] = 1;
			} else {
				/* don't let them in */
				printf("\t\t\tTT%i: Sorry brochacho, can't let you in\n", myIndex);
				ticketTakerCounter_TC3[myIndex] = 0;
			}
			ticketTakerConditionVariable_TC3[myIndex]->Signal(ticketTakerLock_TC3[myIndex]);
			printf("TT has dismissed CUST\n");  //test
			currentThread->Yield();
		} else {
			ticketTakerCounter_TC3[myIndex] = 0;
		}
		
		ticketTakerConditionVariable_TC3[myIndex]->Wait(ticketTakerLock_TC3[myIndex]);
		ticketTakerLock_TC3[myIndex]->Release();
		printf("TT will now look for next customer\n"); //test
	}
}

void obedientCustomersInitialize(){
	

/* INITIALIZATIONS */


/* Ticket Clerk Data */

ticketClerkLineLock_TC3 = new Lock("TicketClerk Line Lock");
		/* for test, only one TC, so index = 0 */
			ticketClerkLineConditionVariable_TC3[0] = new Condition("TicketClerk Line CV");
			ticketClerkLineCount_TC3[0] = 0;		
			ticketClerkLock_TC3[0] = new Lock("TicketClerk Lock");
			ticketClerkConditionVariable_TC3[0] = new Condition("TicketClerk CV");
			ticketClerkRegister_TC3[0] = 0;
			ticketClerkState_TC3[0] = 0;
			
			Thread *r = new Thread("TicketClerk thread");
			r->Fork(obedientCustomerTC, 0);

			
/* Concession Clerk Data */

concessionClerkLineLock_TC3 = new Lock("ConcessionClerk Line Lock");
		/* only one CC for test */
			concessionClerkLineConditionVariable_TC3[0] = new Condition("ConcessionClerk Line CV");
			concessionClerkLineCount_TC3[0] = 0;		
			concessionClerkLock_TC3[0] = new Lock("ConcessionClerk Lock");
			concessionClerkConditionVariable_TC3[0] = new Condition("ConcessionClerk CV");
			concessionClerkRegister_TC3[0] = 0;
			concessionClerkState_TC3[0] = 0;
			
			Thread *s = new Thread("ConcessionClerk thread");
			s->Fork(obedientCustomerCC, 0);
		
			
	
/* Ticket Taker Data */
	
	ticketTakerLineLock_TC3 = new Lock("Ticket Taker Line Lock");
	numberAdmitted_TC3 = 0;
		
			ticketTakerLineConditionVariable_TC3[0] = new Condition("Ticket Taker Line CV");
			ticketTakerConditionVariable_TC3[0] = new Condition("Ticket Taker Interaction CV");
			ticketTakerLineCount_TC3[0] = 0;
			ticketTakerCounter_TC3[0] = 0;
			ticketTakerState_TC3[0] = 0;
			ticketTakerLock_TC3[0] = new Lock("Ticket Taker Interaction Lock");
			
			Thread *t = new Thread("TicketTaker thread");
			t->Fork(obedientCustomerTT, 0);
	
	

/* Head Customer Data */		
		groupSize_TC3[0] = 0;
		
		groupMoney_TC3[0] = 200;
		headCustomerNumber_TC3[0] = 0;  /* Some changes made here for testing, since HeadCustomer doesn't need group to run test. */
		
		/* Thread *t = new Thread("Head Customer");
		t->Fork( headCustomer, i); */


}

void obedientCustomers(){

obedientCustomersInitialize();

Thread *t = new Thread("Head Customer");
		t->Fork( obedientCustomerCust, 0); 
}



/*Test 4: Managers get people off break*/

/*Test 4 "Global Vars*/

void offBreak(){
}

void offBreakInitialize(){
}

/*Test 5: Total Sales never suffers from a race condition*/
/*Test 5 "Global Vars*/

Lock * ticketClerkLockTest[MAX_TC_TEST];
int ticketClerkRegisterTest[MAX_TC_TEST];
int managerMoney;

void totalSalesManager(int myIndex){

	for(int k = 0; k < 4; k++){

		int loopend = rand()%30;
		
		for(int i = 0; i < loopend; i++){
			currentThread->Yield();
		}
		
		for(int j = 0; j < MAX_TC_TEST; j++){
		
			ticketClerkLockTest[j]->Acquire();
			managerMoney += ticketClerkRegisterTest[j];
				
			printf("Manager collected %i from TicketClerk%i.\n", ticketClerkRegisterTest[j], j);
			
			ticketClerkRegisterTest[j] = 0;
		
			ticketClerkLockTest[j]->Release();
		}

		printf("Total money made by office = %i\n", managerMoney);
	}

}

void totalSalesClerk(int myIndex){

	for(int k = 0; k < 4; k++){

		int loopend = rand()%20;
		int numtick = (rand()%5 + 1);

		ticketClerkLockTest[myIndex]->Acquire();
		

		ticketClerkRegisterTest[myIndex] += numtick*10;
		
		printf("TicketClerk %i has an order for %i and the cost is %i.\n", myIndex, numtick, numtick*10);
		
		ticketClerkLockTest[myIndex]->Release();

		for(int i = 0; i < loopend; i++){
			currentThread->Yield();
		}
	}
	
}

void totalSalesInitialize(){



	/*BEGIN: Clerk Initialization*/
		
			
	for ( int i=0; i < MAX_TC_TEST ; i++ ) {
		
		Thread *t = new Thread("Clerk");
		t->Fork( totalSalesClerk, i);
		
		ticketClerkLockTest[i] = new Lock("TicketClerk Lock");
		ticketClerkRegisterTest[i] = 0;
	}	
	
	printf("Number of Ticket Clerks = %i\n",MAX_TC_TEST);
	
	/*END: Clerk Initialization*/

	/*BEGIN: Manager*/
	
	managerMoney = 0;
	Thread *t = new Thread("Manager");
	t->Fork( totalSalesManager, 1);
	
}






/*Test 6: Customer groups always move together*/
/*Test 6 "Global Vars*/

const int maxGroupsTest6 = 2;

Lock * headCustomerLockTest6[maxGroupsTest6];
int customerGroupNumberTest6[maxGroupsTest6*3];
Condition * regularCustomerConditionVariableTest6[maxGroupsTest6];
Condition * headCustomerConditionVariableTest6[maxGroupsTest6];
int customerWantsFoodTest6[maxGroupsTest6*3];
int customerNeedsBathroomTest6[maxGroupsTest6*3];
Lock * RoomLockTest6;


void groupsTogetherRegular(int myIndex){


/*BEGIN: RegularCustomer - HeadCustomer Interaction, Deciding on Food*/

	headCustomerLockTest6[customerGroupNumberTest6[myIndex]]->Acquire();

	/*STEP 1: RegularCustomer waits for Head customer to broadcast (ask them if they want food)*/
	regularCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Wait(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
  
	
	printf("Customer %i in group %i wants food\n",myIndex,customerGroupNumberTest6[myIndex]);
	customerWantsFoodTest6[myIndex] = 1;	
	
	headCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Signal(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);

	
	regularCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Wait(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
		
		printf("Customer %i in group %i has received food!\n",myIndex,customerGroupNumberTest6[myIndex]);


	headCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Signal(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
	regularCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Wait(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
	/*END: RegularCustomer - HeadCustomer Interaction, Deciding on Food*/
	
	/*BEGIN: RegularCustomer - HeadCustomer Interaction, Getting line from head customer*/


	headCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Signal(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
	printf("Customer %i has entered a room and will now wait for head customer to tell him to move\n", myIndex);
	regularCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Wait(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
	printf("Customer %i is now leaving the room\n", myIndex);

	/*END: RegularCustomer - HeadCustomer Interaction, Getting line from head customer*/
	
	
	/*BEGIN: Bathroom deciding*/
	

	printf("Customer %i needs to go to the bathroom!  Telling leader\n", myIndex);
	customerNeedsBathroomTest6[myIndex] = 1;
	
	headCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Signal(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
	regularCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Wait(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);

	printf("Customer %i is back from the bathroom and ready to leave.\n", myIndex);
	
	headCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Signal(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);	
	regularCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Wait(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
	headCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Signal(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);

	/*END: Bathroom deciding*/
	
	regularCustomerConditionVariableTest6[customerGroupNumberTest6[myIndex]]->Wait(headCustomerLockTest6[customerGroupNumberTest6[myIndex]]);
	
	
	headCustomerLockTest6[customerGroupNumberTest6[myIndex]]->Release();
	
	printf("Customer %i in Group %i has left the movie theater\n", myIndex, customerGroupNumberTest6[myIndex]);


}

void groupsTogetherHead(int myIndex){

	for(int i = 0; i < 30; i++){
		currentThread->Yield();
	}
	

	
	/*BEGIN: HeadCustomer - RegularCustomer Interaction for Concessions*/
	 

	/*STEP 1: HeadCustomer - RegularCustomer, Tells all of his "friends" that he's going to order food for them*/
	
	/*Only if the head customer has group members should be acquire the lock, otherwise skip to deciding only for himself*/
	

	
	headCustomerLockTest6[myIndex]->Acquire();
		
	printf("Customer %i in Group %i has entered the movie theater, will first ask other members if they would like food.\n",myIndex,customerGroupNumberTest6[myIndex]);

						
	
	for(int i = 0; i < maxGroupsTest6; i++){
		regularCustomerConditionVariableTest6[myIndex]->Signal(headCustomerLockTest6[myIndex]);
		headCustomerConditionVariableTest6[myIndex]->Wait(headCustomerLockTest6[myIndex]);
	}		
		
	
	printf("Customer %i in Group %i has just gone to go get food and is back\n",myIndex,customerGroupNumberTest6[myIndex]);
	
	for(int i = 0; i < maxGroupsTest6; i++){
		printf("Giving Food to group member\n");
		regularCustomerConditionVariableTest6[myIndex]->Signal(headCustomerLockTest6[myIndex]);
		headCustomerConditionVariableTest6[myIndex]->Wait(headCustomerLockTest6[myIndex]);
	}				
	
	/*END: HeadCustomer - RegularCustomer Interaction for Concessions*/
	
	/* BEGIN entering room */
	
	RoomLockTest6->Acquire();
	
	printf("Customer %i in Group %i has entered the room.\n",myIndex,customerGroupNumberTest6[myIndex]);
	for(int i = 0; i < maxGroupsTest6; i++){
		printf("Customer %i in Group %i is telling Customer %i to follow him into the room.\n",myIndex,customerGroupNumberTest6[myIndex], myIndex*3+1+i);
		regularCustomerConditionVariableTest6[myIndex]->Signal(headCustomerLockTest6[myIndex]);
		headCustomerConditionVariableTest6[myIndex]->Wait(headCustomerLockTest6[myIndex]);
	}	
	
	printf("Customer %i in Group %i been told to exit the room.\n",myIndex,customerGroupNumberTest6[myIndex]);
	
	for(int i = 0; i < maxGroupsTest6; i++){
		printf("Customer %i in Group %i is telling Customer %i to follow him out of the room.\n",myIndex,customerGroupNumberTest6[myIndex], myIndex*3+1+i);
		regularCustomerConditionVariableTest6[myIndex]->Signal(headCustomerLockTest6[myIndex]);
		headCustomerConditionVariableTest6[myIndex]->Wait(headCustomerLockTest6[myIndex]);
	}	
	
	RoomLockTest6->Release();
	
		
	/* BEGIN: Customers in the bathroom*/
	

		//STEP 1: Asking each one if they need to go to the bathrrom
		for(int i = 0; i < maxGroupsTest6; i++){
			regularCustomerConditionVariableTest6[myIndex]->Signal(headCustomerLockTest6[myIndex]);
			headCustomerConditionVariableTest6[myIndex]->Wait(headCustomerLockTest6[myIndex]);
		}		
	
		//Step 2: Allowing the customers to go to the bathroom, or wait in the lobby
	for(int i = 0; i < (maxGroupsTest6); i++){
	
			regularCustomerConditionVariableTest6[myIndex]->Signal(headCustomerLockTest6[myIndex]);
			headCustomerConditionVariableTest6[myIndex]->Wait(headCustomerLockTest6[myIndex]);
		
	}
	
	/* END: Customers going to the bathroom */
	
	
	
	printf("HCust%i: all done! let's get out of here\n", myIndex);
	regularCustomerConditionVariableTest6[myIndex]->Broadcast(headCustomerLockTest6[myIndex]);

	headCustomerLockTest6[myIndex]->Release();
	

	printf("Customer %i in Group %i has left the movie theater\n", myIndex, customerGroupNumberTest6[myIndex]);

}

void groupsTogetherInitialize(){

RoomLockTest6 = new Lock("Room Lock");

	for(int i = 0; i < maxGroupsTest6; i++){

		headCustomerLockTest6[i] = new Lock("Head Customer Lock");
		regularCustomerConditionVariableTest6[i] = new Condition("Reg CV");
		headCustomerConditionVariableTest6[i] = new Condition("Head CV");

	}	

	for(int i = 0; i < maxGroupsTest6*3; i++){

		customerGroupNumberTest6[i] = i/3;
		
		if(i%3 == 0){
			Thread *t = new Thread("Head");
			t->Fork( groupsTogetherHead, i/3);
		}
		else{
			Thread *t = new Thread("Regular");
			t->Fork( groupsTogetherRegular, i);
		}
		
		
	}	


}

void menu(){

	printf("Please choose of the following options.\n");
	printf("1. Customer chooses shortest line.\n");
	printf("2. Manager Collects money from clerks one at a time.\n");
	printf("3. Customers only leave when told, clerks dismiss customers.\n");
	printf("4. Managers get customtrs off break when there are more customers.\n");
	printf("5. Total Sales never suffer from a race condition.\n");
	printf("6. Customers travel in groups together.\n");
	printf("7. Run simulation with default numbers.\n");
	printf("8. Run simulation, input your own numbers.\n");
	printf("9. Our own tests (submenu).\n");

	int choice;
	scanf("%d", &choice);
	
	switch(choice){
	
	case 1:
		shortestLineInitialize();
		break;
	case 2:
		collectMoney();
		break;
	case 3:
		obedientCustomers();
		break;
	case 4:
		offBreakInitialize();
		break;
	case 5:
		totalSalesInitialize();
		break;
	case 6:
		groupsTogetherInitialize();
		break;
	case 7:	
		runTheater();
		break;
	case 8:
		printf("Broken! Doesn't work yet!\n");
		break;
	case 9:
		subMenu();
		break;
	default:
		break;
	}
}

void
ThreadTest()
{
    DEBUG('t', "Entering SimpleTest");


	/*Thread *t = new Thread("Simple Thread");
	t->Fork(SimpleThread, 1);
    SimpleThread(0);*/
	
	
	menu();
	
	
	
	
	/* TestSuite(); */
}
#endif
